package com.shiro.demo.framework.shiro;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.shiro.demo.framework.shiro.AjaxFormAuthenticationFilter;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;

import javax.servlet.Filter;
import javax.sql.DataSource;
import java.util.LinkedHashMap;
import java.util.Map;

@Deprecated
public class ShiroConfig1 {

    /**
     * 配置EhCache
     * 使用配置文件配置EhCacheManager，内部使用net.sf.ehcache.CacheManager实现
     * 这里也可以使用Spring Cache（@EnableCaching）支持，但Spring实现主要是为了实现方法缓存功能，对我们来说功能冗余了
     * @return EhCacheManager
     */
    @Bean
    EhCacheManager ehCacheManager(){
        CacheManager cacheManager = CacheManager.getCacheManager("shiro");
        EhCacheManager ehCacheManager = new EhCacheManager();
        if(cacheManager == null){
            ehCacheManager.setCacheManagerConfigFile("classpath:ehcache/ehcache-shiro.xml");
            return ehCacheManager;
        } else {
            ehCacheManager.setCacheManager(cacheManager);
        }
        return ehCacheManager;
    }

    /**
     * 配置账户信息
     * @param dataSource
     * @return
     */
     @Bean
     public Realm realm(DataSource dataSource){
         JdbcRealm realm = new JdbcRealm();
         realm.setDataSource(dataSource);

         realm.setSaltStyle(JdbcRealm.SaltStyle.COLUMN);
         HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
         matcher.setHashAlgorithmName("MD5");
         matcher.setHashIterations(5);
         matcher.setStoredCredentialsHexEncoded(true);
         realm.setCredentialsMatcher(matcher);

         realm.setSaltStyle(JdbcRealm.SaltStyle.COLUMN);
         return realm;
     }

    /**
     * 配置会话管理器
     */
    DefaultWebSessionManager defaultWebSessionManager(){
        //会话管理器
        DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager();
        EnterpriseCacheSessionDAO enterpriseCacheSessionDAO = new EnterpriseCacheSessionDAO();
        defaultWebSessionManager.setSessionDAO(new EnterpriseCacheSessionDAO());

        return defaultWebSessionManager;
    }

    /**
     * 配置安全管理器
     * @param realm - realm实现
     * @return SecurityManager
     */
    @Bean
    public SecurityManager securityManager(Realm realm) {
        SecurityManager securityManager = new DefaultWebSecurityManager();
        ((DefaultWebSecurityManager) securityManager).setCacheManager(ehCacheManager());
        //账户信息
        ((DefaultWebSecurityManager) securityManager).setRealm(realm);
        return securityManager;
    }

    public SecurityManager securityManager(EhCacheManager ehCacheManager, Realm realm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setCacheManager(ehCacheManager);
        securityManager.setRealm(realm);

        return securityManager;
    }

    /**
     * Shiro过滤器配置
     * 指定登录、未授权url
     * 指定自定义过滤器名称
     * 指定url和过滤器配置
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
    {
        String loginUrl = "/login";

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // Shiro的核心安全接口,这个属性是必须的
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 身份认证失败，则跳转到登录页面的配置
        shiroFilterFactoryBean.setLoginUrl(loginUrl);
        // 权限认证失败，则跳转到指定页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/error");
        shiroFilterFactoryBean.setSuccessUrl("/");
        //自定义过滤器
        Map<String, Filter> filters = new LinkedHashMap<>();
        AjaxFormAuthenticationFilter formAuthenticationFilter = new AjaxFormAuthenticationFilter();
        filters.put("formAuthenticationFilter", formAuthenticationFilter);
        shiroFilterFactoryBean.setFilters(filters);
        // Shiro连接约束配置，即过滤链的定义
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();

        //受保护的Url
        filterChainDefinitionMap.put("/secured/**", "user");
        //注销
        filterChainDefinitionMap.put("/logout", "logout");
        //登陆
        filterChainDefinitionMap.put("/login", "formAuthenticationFilter");
        //其它资源可匿名访问
        filterChainDefinitionMap.put("/**", "anon");

        shiroFilterFactoryBean.setUnauthorizedUrl("/error/unauth");

        return shiroFilterFactoryBean;
    }

    /**
     * thymeleaf模板引擎和shiro框架的整合
     */
    @Bean
    public ShiroDialect shiroDialect()
    {
        return new ShiroDialect();
    }

    /**
     * 开启Shiro注解通知器
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
            @Qualifier("securityManager") SecurityManager securityManager)
    {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * 控制Shiro组件生命周期
     * @return
     */
    @Bean
    LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }
}
